/** ***********************************************************************************
* @file         save_task.c
* @brief        数据存储处理任务
* @details      主要用来处理发送的数据进行数据存现
* @author       杨小珛
* @date         2021/3/7
* @copyright    北京高知科技有限公司    
* @version      V1.0
* @attention    无
**************************************************************************************/
#include "save_task.h"
#include "log_task.h"
#include "mon_task.h"
#include "com_lib.h"

#define SAVE_MAN_NAME  "SAVE_MAN_TASK"
GaozQueueHandle_t save_data_queue; /*定义网络发送数据消息队列*/
GaozMutexHandle_t save_data_mutex; //数据互斥
save_ram_data_infor_t ram_buffer[SAVE_RAM_OPEN_MAX_NUM];
static save_data_infor_t save_infor;
save_data_flash_state_e save_data_flash_st;
save_mcu_data_infor_t save_mcu_data_infor;
static void save_data_handle_task( void * pvParameters );
static void save_data_queue_create(void);
static uint32_t save_data_queue_get( save_data_infor_t *save_msg );


static uint32_t save_ram_unit_write( uint32_t handle_id ,uint8_t *data, uint16_t dlen );
static uint32_t save_ram_head_data_get( uint32_t handle_id ,uint8_t *data, uint16_t *dlen );
static uint32_t save_ram_cache_data_get( uint32_t handle_id ,uint8_t *data, uint16_t *dlen );
static uint32_t save_ram_tail_data_get( uint32_t handle_id ,uint8_t *data, uint16_t *dlen );
static uint32_t save_ram_data_len_get( uint32_t handle_id ,uint16_t *dlen );
static void save_data_printf_data_fun( save_data_mode_e mode , uint32_t handle_id , uint8_t * p_data , uint16_t d_len );

/** ****************************************************************************
* @remarks       void save_data_create_task( unsigned portBASE_TYPE uxPriority )
* @brief         数据存储管理任务
* @param[in]     uxPriority任务优先级；
* @param[out]    无
* @return        无
* @attention     在系统启动后进行创建
*******************************************************************************/
void save_data_create_task( unsigned portBASE_TYPE uxPriority )
{   
    memset((uint8_t *)ram_buffer , 0x00 , sizeof(save_ram_data_infor_t) *SAVE_RAM_OPEN_MAX_NUM );
    save_data_mutex = gaoz_mutex_create();/*创建系统日志互斥体*/
    if(save_data_mutex == 0)
    {
        while(1); /*创建信号量失败*/
    }
    save_data_queue_create();
    gaoz_thread_create(save_data_handle_task, SAVE_MAN_NAME, 1024*2, NULL, uxPriority);
}


/** ****************************************************************************
* @remarks       void save_data_bbt_tables_init( void )
* @brief         初始数据存储空间
* @param[in]     无
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
void save_data_bbt_tables_init( void )
{
    if( sfb_bbt_tables_init() == pdPASS )
    {
        save_data_flash_st = SAVE_DATA_FLASH_OK;
    }
    else
    {
        save_data_flash_st = SAVE_DATA_FLASH_ERR;
    }
}


/** ****************************************************************************
* @remarks       save_data_flash_state_e save_data_flash_state_get( void )
* @brief         获取FLASH 状态
* @param[in]     无
* @param[out]    无
* @return        返回FLASH的工作状态 SAVE_DATA_FLASH_ERR：失败 SAVE_DATA_FLASH_OK：成功
* @attention     无
*******************************************************************************/
save_data_flash_state_e save_data_flash_state_get( void )
{
    return save_data_flash_st;
}

/** ****************************************************************************
* @remarks       static void save_data_queue_create(void)
* @brief         创建 保存数据消息队列
* @param[in]     无
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
static void save_data_queue_create(void)
{
    /* 创建模块网络发送数据的消息队列 */
    save_data_queue = gaoz_queue_create( SAVE_DATA_QUEUE_DEPTH, sizeof( save_data_infor_t ) );
    if( save_data_queue == 0 )
    {
        while( 1 ); /*创建失败,进行处理*/
    }   
}
/** ****************************************************************************
* @remarks       static uint32_t save_data_queue_get( save_data_infor_t *save_msg )
* @brief         获取SAVE数据发送消息队列数据
* @param[in]     *save_msg 获取的数据地址
* @param[out]    无
* @return        pdPASS 接收到数据 pdFAIL 未接收到数据
* @attention     必须在任务中运行
*******************************************************************************/
static uint32_t save_data_queue_get( save_data_infor_t *save_msg )
{
    if( save_data_queue == 0 )
    {
        save_data_queue_create();
    }
    if( gaoz_queue_get( save_data_queue, save_msg, SAVE_DATA_WAIT_TIME )  == 0 ) //等待回应信号量
    {
        return pdPASS;
    }
    else
    {
        return pdFAIL;
    }
    
    return pdFAIL;
}

/** ****************************************************************************
* @remarks       uint32_t save_data_open( sfb_buf_rt_t *sfb_handle ,const sfb_setting_t *sfb_set , uint32_t *handle_id )
* @brief         打开SAVE 数据，进行初始
* @param[in]     *sfb_handle SFB 句柄地址
* @param[in]     *sfb_set SFB设置的地址参数
* @param[out]    *handle_id
* @return        pdPASS 成功 pdFAIL 失败
* @attention     必须在任务中运行
*******************************************************************************/
uint32_t save_data_open( sfb_buf_rt_t *sfb_handle ,const sfb_setting_t *sfb_set , uint32_t *handle_id )
{
    uint8_t num = 0;
    uint32_t osR = 0 , res = pdFAIL ,len = 0;
    if(( sfb_handle == NULL ) || ( sfb_set == NULL ))
    {
        return pdFAIL;
    }
    if( save_data_mutex != 0 )
    {   
        gaoz_mutex_lock( save_data_mutex );
        osR = 1;
    }
    /*申请一段空间，进行RAM数据的存储*/
    for( num = 0 ; num < SAVE_RAM_OPEN_MAX_NUM ; num ++ )
    {
        if( ram_buffer[num].sfb_handle == NULL )
        {   
            /*初始化FLASH 数据空间参数*/
            ram_buffer[num].handle_num = sfb_handle_init( sfb_handle ,sfb_set );
            ram_buffer[num].sfb_handle = sfb_handle;
            len = ram_buffer[num].sfb_handle->sfb_set.unit_sz * SAVE_RAM_DATA_MAX_NUM;
            if( len  <= SPI_FLASH_MIN_SECTOR )
            {
                ram_buffer[num].ram_buf = (uint8_t *)gaoz_fibo_malloc( len );
                if( ram_buffer[num].ram_buf != NULL )
                {
                    memset((uint8_t *)ram_buffer[num].ram_buf , 0x00 , len );
                    *handle_id = num;
                    res = pdPASS;
                }
                ram_buffer[num].ram_num = 0; 
            }
            break;
        }
    }
    if( res == pdPASS )
    {
        log_debug_printf( DEBUG_MODE,SAVE_MAN_NAME ,"Save data management open successful handle num:%d\r\n",ram_buffer[num].handle_num );
    }
    else
    {
        log_debug_printf( DEBUG_MODE,SAVE_MAN_NAME ,"[%s]Save data management open failure handle num:%d\r\n",sys_err_infor_pointer_get( 5 ),ram_buffer[num].handle_num );
    }
    if(osR != 0)
    {
        gaoz_mutex_unlock( save_data_mutex );
    }    
    return res;
}

/** ****************************************************************************
* @remarks       uint32_t save_data_write( uint32_t handle_id ,uint8_t *data, uint16_t dlen )
* @brief         写FLASH 数据
* @param[in]     handle_id 句柄ID
* @param[in]     *data 保存的数据地址
* @param[in]     dlen 保存的数据长度
* @param[out]    无
* @return        pdPASS 成功 ， pdFAIL 失败
* @attention     可重入函数 内部互斥
*******************************************************************************/
uint32_t save_data_write( uint32_t handle_id ,uint8_t *data, uint16_t dlen )
{
    uint32_t osR = 0 , res = pdFAIL;
    uint8_t *pbuf = NULL;
    
    if(( handle_id >= SAVE_RAM_OPEN_MAX_NUM ) || ( data == NULL ) || ( dlen == 0 ))
    {
        return pdFAIL;
    }
    if( save_data_mutex != 0 )
    {
        gaoz_mutex_lock( save_data_mutex );
        osR = 1;
    }
    
    if( dlen > ram_buffer[handle_id].sfb_handle->sfb_set.unit_sz )
    {
        if(osR != 0)
        {   
            gaoz_mutex_unlock( save_data_mutex );
       }
       return pdFAIL;
    }
    
    pbuf = (uint8_t *)gaoz_malloc_mem( dlen + 8 ); /*动态申请空间，空间位置处于FreeRtos总栈空间中*/
    if( pbuf == NULL )
    {
        if(osR != 0)
        {   
            gaoz_mutex_unlock( save_data_mutex );
        }
        return pdFAIL;
    }
    save_infor.handle_id = handle_id;
    memcpy((uint8_t *)pbuf ,(uint8_t *)data , dlen );
    save_infor.data = pbuf;
    save_infor.len = dlen;
    res = gaoz_queue_put( save_data_queue,&save_infor,SAVE_DATA_FALSH_WRITE_TIME );
    if( res == 0 )
    {
        res = pdPASS;
    }
    else
    {
        /*消息发送失败，或者消息队列已满*/
        gaoz_free_mem((void *)pbuf);
        log_debug_printf( ERROR_MODE,SAVE_MAN_NAME ,"[%s]Save data queue is full\r\n",sys_err_infor_pointer_get( 6 ));
        res = pdFAIL;
    }
    
    if(osR != 0)
    {   
        gaoz_mutex_unlock( save_data_mutex );
    }
    
    return  res;
}

/** ****************************************************************************
* @remarks       uint32_t save_data_read( uint32_t handle_id ,uint8_t *data, uint16_t *dlen )
* @brief         读FLASH 数据
* @param[in]     handle_id SAVE句柄ID
* @param[out]    *data 数据的目标地址
* @param[out]    *dlen 数据的长度
* @return        返回 数据包的长度 等于0时没有数据
* @attention     可重入函数 内部互斥
*******************************************************************************/
uint32_t save_data_read( uint32_t handle_id ,uint8_t *data, uint16_t *dlen )
{
    uint32_t osR = 0 , res = pdFAIL , flash_num = 0;
    uint16_t ram_num = 0;
    sfb_index_t rindex;
    sfb_buf_rt_t *sfb_handle = NULL;
    uint32_t *handle_num = NULL;
    /* 上锁，保护数据读取 */
    if( save_data_mutex != 0 )
    {
        gaoz_mutex_lock( save_data_mutex );
        osR = 1;
    }
    if( handle_id >= SAVE_RAM_OPEN_MAX_NUM )
    {
        return pdFAIL;
    }
    sfb_handle = ram_buffer[handle_id].sfb_handle;
    handle_num = &ram_buffer[handle_id].handle_num;
    /* 读取RAM 与 FLASH空间中的数据长度*/
    save_ram_data_len_get( handle_id ,&ram_num );
    sfb_units_cn_get( sfb_handle, &flash_num ); /*获取FLASH存储的数据条目数*/
    /*RAM中有数据*/
    if( ram_num != 0 )
    {   
        /*读取RAM头空间地址中的数据*/
        res = save_ram_head_data_get( handle_id ,data, dlen );
        if( res == pdFAIL )
        {
            /*读取RAM缓存空间地址中的数据*/
            res = save_ram_cache_data_get( handle_id ,data, dlen );
            if( res == pdFAIL )
            {
                res = 0xFFFFFFFF;
            }
        }
    }
    else/* RAM中没有数据，开始读取FLASH中的数据*/
    {
        if( flash_num != 0 )
        {
            /*读取FLASH缓存空间中的数据*/
            memset((uint8_t *)&rindex , 0xFF , sizeof( sfb_index_t ));
            res = sfb_unit_read( sfb_handle , SFB_SEARCH_CYCLE, 1, SPI_FLASH_MIN_SECTOR, data ,&rindex);
            if( res == pdPASS )
            {
                if( calculate_crc8( data ,rindex.usdatalen ) == rindex.ucsfcrc )
                {
                    *dlen = rindex.usdatalen;
                    #if 1
                    sfb_send_succ( sfb_handle );/* 读取FLASH数据成功 */
                    sfb_write_handle_position( sfb_handle, handle_num );
                    #endif
                }
                else
                {
                    *dlen = 0;
                    res = 0xFFFFFFFF;
                }
            }
            else
            {
                log_debug_printf( ERROR_MODE,SAVE_MAN_NAME ,"[%s]Save data management read data error,handle is:%d\r\n",sys_err_infor_pointer_get( 7 ),handle_id );
                res = 0xFFFFFFFF;
            }   
        }
    }
    /*打印读取的数据*/
    if( res == pdPASS )
    {
        save_data_printf_data_fun( SAVE_DATA_READ , handle_id , data , *dlen );
        log_debug_printf( DEBUG_MODE,SAVE_MAN_NAME ,"Save data management read num:%d,%d(RAM,FLASH)\r\n",ram_num , flash_num );
    }
    /* 解锁 */
    if(osR != 0)
    {   
        gaoz_mutex_unlock( save_data_mutex );
    }
    /*读取数据失败*/
    if( res == 0xFFFFFFFF )
    {
        return res;
    }
    return ( ram_num + flash_num );
}

/** ****************************************************************************
* @remarks       uint32_t save_data_close( uint32_t handle_id )
* @brief         关闭FLASH 句柄操作
* @param[in]     handle_id SAVE句柄id
* @param[out]    无
* @return        pdPASS  成功 ， pdFAIL  失败
* @attention     可重入函数 内部互斥
*******************************************************************************/
uint32_t save_data_close( uint32_t handle_id )
{
    uint32_t osR = 0 ;
    
    if( save_data_mutex != 0 )
    {
        gaoz_mutex_lock( save_data_mutex );
        osR = 1;
    }

    if( handle_id >= SAVE_RAM_OPEN_MAX_NUM )
    {
        return pdFAIL;
    }
    /*清空内存空间数据*/
    sfb_block_reset( ram_buffer[handle_id].sfb_handle->sfb_set.handle_add, 1 );
    ram_buffer[handle_id].sfb_handle = NULL;
    ram_buffer[handle_id].handle_num = 0;
    ram_buffer[handle_id].ram_num = 0;
    gaoz_fibo_free( (void *)ram_buffer[handle_id].ram_buf );
    ram_buffer[handle_id].ram_buf = NULL;
    
    if(osR != 0)
    {   
        gaoz_mutex_unlock( save_data_mutex );
    }
    
    return pdPASS;
}

/** ****************************************************************************
* @remarks       static uint32_t save_ram_unit_write( uint32_t handle_id ,uint8_t *data, uint16_t dlen )
* @brief         写RAM数据
* @param[in]     handle_id SFB数据句柄 id
* @param[in]     *data 数据源地址
* @param[int]    *dlen 数据长度
* @return        无
* @attention     无
*******************************************************************************/
static uint32_t save_ram_unit_write( uint32_t handle_id ,uint8_t *data, uint16_t dlen )
{   
    uint32_t res = pdFAIL ,offset_addr = 0 , cache_addr = 0;
    uint8_t num = 0 , pos = 0;
    uint8_t *head_p = NULL , *cache_p = NULL, *tail_p = NULL;
    /*检查数据是否正常*/
    if(( handle_id >= SAVE_RAM_OPEN_MAX_NUM ) || ( data == NULL ) )
    {
        return pdFAIL;
    }
    /*查找对应句柄的位置*/
    num = handle_id;
    res = pdPASS;
    if( res == pdPASS )
    {   /*最长数据不能大于设置的数据*/
        if( dlen > ram_buffer[num].sfb_handle->sfb_set.unit_sz ) 
        {
            return pdFAIL;
        }
        /*将数据地址进行划分*/
        head_p = &ram_buffer[num].ram_buf[0];
        cache_p = &ram_buffer[num].ram_buf[ram_buffer[num].sfb_handle->sfb_set.unit_sz];
        tail_p = &ram_buffer[num].ram_buf[ram_buffer[num].sfb_handle->sfb_set.unit_sz * ( SAVE_RAM_DATA_MAX_NUM - 1 )];
        /*检测头地址是否已经已经更新数据，没有数据重新填充新的数据*/
        if( ram_buffer[num].head_flag == 0 )
        {   
            memset((uint8_t *)head_p , 0x00 , ram_buffer[num].sfb_handle->sfb_set.unit_sz );
            head_p[0] = ( uint8_t )(( dlen & 0xFF00 ) >> 8 );
            head_p[1] = ( uint8_t )( dlen & 0x00FF );
            memcpy(( uint8_t *)&head_p[2],( uint8_t *)data ,dlen );
            ram_buffer[num].head_flag = 1;
        }
        else
        {
            if( ram_buffer[num].cache_len == SAVE_RAM_DATA_NUM )      /*数据空间已经存储完毕*/
            {
                ram_buffer[num].cache_len = SAVE_RAM_DATA_NUM;
                /*将最后缓存空间中的最后一包数据存放到尾地址空间*/
                offset_addr = ( SAVE_RAM_DATA_NUM - 1 ) * ram_buffer[num].sfb_handle->sfb_set.unit_sz;
                memcpy(( uint8_t *)tail_p,( uint8_t *)&cache_p[offset_addr] ,ram_buffer[num].sfb_handle->sfb_set.unit_sz );
                ram_buffer[num].tail_flag = 1;
                /*将所有数据进行向下移动*/
                for( pos = 1 ; pos < SAVE_RAM_DATA_NUM ; pos++ )
                {
                    offset_addr = ( SAVE_RAM_DATA_NUM - pos ) * ram_buffer[num].sfb_handle->sfb_set.unit_sz;
                    cache_addr = ( SAVE_RAM_DATA_NUM - pos - 1 ) * ram_buffer[num].sfb_handle->sfb_set.unit_sz;
                    memcpy(( uint8_t *)&cache_p[offset_addr],( uint8_t *)&cache_p[cache_addr],ram_buffer[num].sfb_handle->sfb_set.unit_sz );
                }
                memcpy(( uint8_t *)&cache_p[0],( uint8_t *)head_p ,ram_buffer[num].sfb_handle->sfb_set.unit_sz );
                /*将最新数据进行缓存*/
                memset((uint8_t *)head_p , 0x00 , ram_buffer[num].sfb_handle->sfb_set.unit_sz );
                head_p[0] = ( uint8_t )(( dlen & 0xFF00 ) >> 8 );
                head_p[1] = ( uint8_t )( dlen & 0x00FF );
                memcpy(( uint8_t *)&head_p[2],( uint8_t *)data ,dlen );
                ram_buffer[num].head_flag = 1;
            }
            else
            {
                /*拷贝头地址空间中的数据*/
                if( ram_buffer[num].cache_len == 0 )
                {
                    offset_addr = ram_buffer[num].cache_len * ram_buffer[num].sfb_handle->sfb_set.unit_sz;
                    memcpy(( uint8_t *)&cache_p[offset_addr],( uint8_t *)head_p ,ram_buffer[num].sfb_handle->sfb_set.unit_sz );
                }
                else
                {
                    /*将所有数据进行向下移动*/
                    for( pos = 0 ; pos < ram_buffer[num].cache_len ; pos++ )
                    {
                        offset_addr = ( ram_buffer[num].cache_len - pos ) * ram_buffer[num].sfb_handle->sfb_set.unit_sz;
                        cache_addr = ( ram_buffer[num].cache_len - pos - 1 ) * ram_buffer[num].sfb_handle->sfb_set.unit_sz;
                        memcpy(( uint8_t *)&cache_p[offset_addr],( uint8_t *)&cache_p[cache_addr],ram_buffer[num].sfb_handle->sfb_set.unit_sz );
                    }
                    memcpy(( uint8_t *)&cache_p[0],( uint8_t *)head_p ,ram_buffer[num].sfb_handle->sfb_set.unit_sz );
                }
                ram_buffer[num].cache_len++;
                /*将最新数据进行缓存*/
                memset((uint8_t *)head_p , 0x00 , ram_buffer[num].sfb_handle->sfb_set.unit_sz );
                head_p[0] = ( uint8_t )(( dlen & 0xFF00 ) >> 8 );
                head_p[1] = ( uint8_t )( dlen & 0x00FF );
                memcpy(( uint8_t *)&head_p[2],( uint8_t *)data ,dlen );
                ram_buffer[num].head_flag = 1;
            }
        }
    }
    return res;
}

/** ****************************************************************************
* @remarks       uint32_t save_ram_head_data_get( sfb_buf_rt_t *sfb_handle ,uint8_t *data, uint16_t *dlen )
* @brief         获取头部存储的数据
* @param[in]     *sfb_handle SFB数据句柄
* @param[out]    *data 数据目标地址
* @param[out]    *dlen 数据长度
* @return        无
* @attention     无
*******************************************************************************/
static uint32_t save_ram_head_data_get( uint32_t handle_id ,uint8_t *data, uint16_t *dlen )
{   
    uint8_t num = 0;
    uint8_t *head_p = NULL;
    uint32_t res = pdFAIL;
    
    *dlen = 0;
    /*检查数据是否正常*/
    if(( handle_id >= SAVE_RAM_OPEN_MAX_NUM ) || ( data == NULL ))
    {
        return pdFAIL;
    }
    /*查找对应句柄的位置*/
    num = handle_id;
    /*获取tail控制地址*/
    head_p = &ram_buffer[num].ram_buf[0];
    /*查找tail数据是否有效*/
    if( ram_buffer[num].head_flag == 1 )
    {
        ram_buffer[num].head_flag = 0;
        *dlen = head_p[0] * 256 + head_p[1];
        memcpy((uint8_t *)data , (uint8_t *)&head_p[2], *dlen );
        memset((uint8_t *)head_p, 0x00, ram_buffer[num].sfb_handle->sfb_set.unit_sz );
        res = pdPASS;
    }
    return res;
}

/** ****************************************************************************
* @remarks       uint32_t save_ram_cache_data_get( sfb_buf_rt_t *sfb_handle ,uint8_t *data, uint16_t *dlen )
* @brief         获取缓存的数据
* @param[in]     *sfb_handle SFB数据句柄
* @param[out]    *data 数据目标地址
* @param[out]    *dlen 数据长度
* @return        无
* @attention     无
*******************************************************************************/
static uint32_t save_ram_cache_data_get( uint32_t handle_id ,uint8_t *data, uint16_t *dlen )
{   
    uint8_t num = 0;
    uint8_t *cache_p = NULL;
    uint32_t res = pdFAIL, offset_addr = 0;
    
    *dlen = 0;
    /*检查数据是否正常*/
    if(( handle_id >= SAVE_RAM_OPEN_MAX_NUM ) || ( data == NULL ))
    {
        return pdFAIL;
    }
    /*查找对应句柄的位置*/
    num = handle_id;
    /*获取tail控制地址*/
    cache_p = &ram_buffer[num].ram_buf[ram_buffer[num].sfb_handle->sfb_set.unit_sz];
    /*查找tail数据是否有效*/
    if( ram_buffer[num].cache_len > 0 )
    {
        offset_addr = ( ram_buffer[num].cache_len - 1 ) * ram_buffer[num].sfb_handle->sfb_set.unit_sz;
        *dlen = cache_p[offset_addr + 0] * 256 + cache_p[offset_addr + 1];
        memcpy((uint8_t *)data , (uint8_t *)&cache_p[offset_addr + 2], *dlen );
        memset((uint8_t *)&cache_p[offset_addr], 0x00, ram_buffer[num].sfb_handle->sfb_set.unit_sz );
        ram_buffer[num].cache_len --;
        res = pdPASS;
    }
    return res;
}

/** ****************************************************************************
* @remarks       uint32_t save_ram_tail_data_get( sfb_buf_rt_t *sfb_handle ,uint8_t *data, uint16_t *dlen )
* @brief         获取尾部存储的数据
* @param[in]     *sfb_handle SFB数据句柄
* @param[out]    *data 数据目标地址
* @param[out]    *dlen 数据长度
* @return        无
* @attention     无
*******************************************************************************/
static uint32_t save_ram_tail_data_get( uint32_t handle_id ,uint8_t *data, uint16_t *dlen )
{   
    uint8_t num = 0;
    uint8_t *tail_p = NULL;
    uint32_t res = pdFAIL;
    
    *dlen = 0;
    /*检查数据是否正常*/
    if(( handle_id >= SAVE_RAM_OPEN_MAX_NUM ) || ( data == NULL ))
    {
        return pdFAIL;
    }
    /*查找对应句柄的位置*/
    num = handle_id;    
    /*获取tail控制地址*/
    tail_p = &ram_buffer[num].ram_buf[ram_buffer[num].sfb_handle->sfb_set.unit_sz * ( SAVE_RAM_DATA_MAX_NUM - 1 )];
    /*查找tail数据是否有效*/
    if( ram_buffer[num].tail_flag == 1 )
    {
        ram_buffer[num].tail_flag = 0;
        *dlen = tail_p[0] * 256 + tail_p[1];
        memcpy((uint8_t *)data , (uint8_t *)&tail_p[2], *dlen );
        memset((uint8_t *)tail_p, 0x00, ram_buffer[num].sfb_handle->sfb_set.unit_sz );
        res = pdPASS;
    }
    return res;
}

/** ****************************************************************************
* @remarks       static uint32_t save_ram_data_len_get( sfb_buf_rt_t *sfb_handle ,uint16_t *dlen )
* @brief         获取RAM空间数据的长度
* @param[in]     *sfb_handle SFB数据句柄
* @param[out]    *dlen 数据长度
* @return        无
* @attention     无
*******************************************************************************/
static uint32_t save_ram_data_len_get( uint32_t handle_id ,uint16_t *dlen )
{
    uint32_t res = pdFAIL;
    uint8_t num = 0;
    
    *dlen = 0;
    /*检查数据是否正常*/
    if( handle_id >= SAVE_RAM_OPEN_MAX_NUM )
    {
        return pdFAIL;
    }
    /*查找对应句柄的位置*/
    num = handle_id;
    
    if( ram_buffer[num].head_flag == 1 ) 
    {
        *dlen += 1;
    }
    if( ram_buffer[num].cache_len > 0 )
    {
        *dlen += ram_buffer[num].cache_len;
    }
    
    return res;
}

/** ****************************************************************************
* @remarks       uint32_t save_mcu_data_infor_init( void )
* @brief         MCU关键信息初始化，主要就是用来读取当前最新的数据。
* @param[in]     无
* @param[out]    无
* @return        pdPASS 成功，pdFAIL 失败；
* @attention     无
*******************************************************************************/
uint32_t save_mcu_data_infor_init( void )
{
    uint32_t  res = pdFAIL;
    #if 0
    #define CRC_ERROR   ( 0x01 )
    #define READ_ERROR  ( 0x02 )
    #define DATA_OK     ( 0x04 )
    uint8_t *infor_p = NULL, j = 0, crc8 = 0, finish = 0;
    uint32_t read_addr = 0, i = 0, res = pdFAIL;
    save_mcu_data_infor_t *infor_t = NULL;

    infor_p = (uint8_t *)gaoz_fibo_malloc( SPI_FLASH_MIN_SECTOR );
    if( infor_p != NULL )
    {
        for( i = 0; i < SF_MCU_DATA_FLAG_SECTORS; i ++ )
        {
            read_addr = i * SPI_FLASH_MIN_SECTOR + SF_MCU_DATA_ADDR;;
            if( sfb_read_buf( read_addr, (uint8_t *)infor_p, SPI_FLASH_MIN_SECTOR ) == pdPASS )
            {
                for( j = 0; j < ( SPI_FLASH_MIN_SECTOR / MCU_DATA_BLOCK_SIZE ); j++ )
                {
                    infor_t = (save_mcu_data_infor_t *)&infor_p[j*MCU_DATA_BLOCK_SIZE];
                    crc8 = calculate_crc8( (uint8_t *)infor_t, ( MCU_DATA_BLOCK_SIZE - 1 ));
                    if( infor_t->crc == crc8 )
                    {
                        if( ( infor_t->period * SF_MCU_DATA_SIZE / MCU_DATA_BLOCK_SIZE + infor_t->once ) <
                            ( save_mcu_data_infor.period * SF_MCU_DATA_SIZE / MCU_DATA_BLOCK_SIZE + save_mcu_data_infor.once ) )
                        {
                            finish |= READ_ERROR;
                            break;  /*读取到的节点数据比上一条小，说明读到了最后一包数据。结束读取*/
                        }
                        else
                        {
                            finish |= DATA_OK;
                            memcpy( (uint8_t *)&save_mcu_data_infor, (uint8_t *)infor_t, sizeof( save_mcu_data_infor_t ));
                        }
                    }
                    else
                    {
                        finish |= CRC_ERROR;
                        break;      /*CRC校验未通过，认为读到最后一包数据。结束读取*/
                    }
                }
            }
            else
            {
                break;
            }
            if( (( finish & CRC_ERROR ) == CRC_ERROR) || ((finish & READ_ERROR ) == READ_ERROR) )
            {
                break;
            }
        }
        gaoz_fibo_free( (void *)infor_p );
    }
    /*判断读取的数据是否有效,如果有效将返回标志位置为0*/
    if(( finish & DATA_OK ) == DATA_OK )
    {
        log_debug_printf( DEBUG_MODE,SAVE_MAN_NAME ,"save mcu data infor read:period=%d,once=%d\r\n",save_mcu_data_infor.period, save_mcu_data_infor.once );
        save_mcu_data_infor.once ++;    /*存储指针向后加一，例如读取到最后的数据指针为4，下一条应该存储到5的位置*/
        if( save_mcu_data_infor.once == ( SF_MCU_DATA_SIZE / MCU_DATA_BLOCK_SIZE ) )
        {
            save_mcu_data_infor.period ++;
            save_mcu_data_infor.once = 0;
        }
        res = pdPASS; 
    }
    #endif
    
    return res;
}

/** ****************************************************************************
* @remarks       uint32_t save_mcu_data_infor_write( uint8_t *data, uint8_t len )
* @brief         写MCU关键性数据信息
* @param[in]     *data 数据源地址
* @param[out]    *dlen 数据长度
* @return        pdPASS 成功，pdFAIL 失败；
* @attention     无
*******************************************************************************/
uint32_t save_mcu_data_infor_write( uint8_t *data, uint8_t dlen )
{
    #if 0
    uint32_t write_addr = 0;

    if(( data == NULL ) || ( dlen > MCU_DATA_INFOR_SIZE ))
    {
        return pdFAIL;
    }
    /*判断地址是否处于整块地址开始，如果是进行擦擦。*/
    write_addr = save_mcu_data_infor.once * MCU_DATA_BLOCK_SIZE + SF_MCU_DATA_ADDR;
    if(( write_addr  % SPI_FLASH_MIN_SECTOR ) == 0 )
    {
        sfb_block_reset( write_addr , 1 ); 
    }
    /*将数据写入到消息结构体中，写入到外部FLASH*/
    save_mcu_data_infor.len = dlen;
    memset( (uint8_t *)save_mcu_data_infor.data, 0xFF, MCU_DATA_INFOR_SIZE );
    memcpy( (uint8_t *)save_mcu_data_infor.data, data, dlen );
    save_mcu_data_infor.crc = calculate_crc8( (uint8_t *)&save_mcu_data_infor, ( MCU_DATA_BLOCK_SIZE - 1) );
    log_debug_printf( DEBUG_MODE,SAVE_MAN_NAME ,"save mcu data infor write:addr=0x%08x,period=%d,once=%d\r\n",write_addr, save_mcu_data_infor.period, save_mcu_data_infor.once );
    if( sfb_write_buf( write_addr, (uint8_t *)&save_mcu_data_infor, MCU_DATA_BLOCK_SIZE ) != pdPASS )
    {
        log_debug_printf( DEBUG_MODE,SAVE_MAN_NAME ,"save mcu data infor write ERROR!!!\r\n" );
        memset((uint8_t *)&save_mcu_data_infor, 0x00, sizeof( save_mcu_data_infor_t ));
        return pdFAIL;
    }
    
    /*位置进行增加，判断位置是否为最后一个。如果是清零并对周期标记加一操作。*/
    save_mcu_data_infor.once ++;
    if( save_mcu_data_infor.once == ( SF_MCU_DATA_SIZE / MCU_DATA_BLOCK_SIZE ) )
    {
        save_mcu_data_infor.period ++;
        save_mcu_data_infor.once = 0;
    }

    return pdPASS;
    #endif
    return pdFAIL;
}

/** ****************************************************************************
* @remarks       uint32_t save_mcu_data_infor_read( uint8_t *data, uint8_t dlen )
* @brief         读取MCU关键性数据信息（最新的数据）
* @param[out]    *data 数据目标地址
* @param[out]    *dlen 数据长度
* @return        pdPASS 成功，pdFAIL 失败；
* @attention     无
*******************************************************************************/
uint32_t save_mcu_data_infor_read( uint8_t *data, uint8_t *dlen )
{
    uint32_t res = pdFAIL;

    #if 0

    if(( data == NULL ) || ( dlen == NULL ))
    {
        return pdFAIL;
    }
    
    if(( save_mcu_data_infor.period * SF_MCU_DATA_SIZE / MCU_DATA_BLOCK_SIZE + save_mcu_data_infor.once ) != 0 )
    {
        *dlen = save_mcu_data_infor.len;
        memcpy( (uint8_t *)data, (uint8_t *)save_mcu_data_infor.data,  save_mcu_data_infor.len );
        res = pdPASS;
    }
    #endif
    
    return res;
}

/** ****************************************************************************
* @remarks       uint32_t save_vin_data_infor_write( uint8_t *data, uint16_t dlen )
* @brief         写VIN关键性数据信息
* @param[in]     *data 数据源地址
* @param[in]    *dlen 数据长度
* @return        pdPASS 成功，pdFAIL 失败；
* @attention     无
*******************************************************************************/
uint32_t save_vin_data_infor_write( uint8_t *data, uint16_t dlen )
{
    if(( data == NULL ) || ( dlen > SF_VIN_DATA_SIZE ))
    {
        return pdFAIL;
    }
    sfb_block_reset( SF_VIN_DATA_ADDR , 1 ); 
    return sfb_write_buf( SF_VIN_DATA_ADDR, (uint8_t *)data, dlen );
}

/** ****************************************************************************
* @remarks       uint32_t save_vin_data_infor_write( uint8_t *data, uint16_t dlen )
* @brief         读取VIN关键性数据信息
* @param[in]     dlen 读取数据长度
* @param[out]    *data 数据目标地址地址
* @return        pdPASS 成功，pdFAIL 失败；
* @attention     无
*******************************************************************************/
uint32_t save_vin_data_infor_read( uint8_t *data, uint16_t dlen )
{
    return sfb_read_buf( SF_VIN_DATA_ADDR, (uint8_t *)data, dlen );
}

/** ****************************************************************************
* @remarks       uint32_t save_reset_reason_write( uint8_t *data, uint16_t dlen )
* @brief         存储设备重启原因
* @param[in]     *data 数据源地址
* @param[in]    *dlen 数据长度
* @return        pdPASS 成功，pdFAIL 失败；
* @attention     无
*******************************************************************************/
uint32_t save_reset_reason_write( uint8_t *data, uint16_t dlen )
{
    if(( data == NULL ) || ( dlen > SF_RESET_REASON_SIZE ))
    {
        return pdFAIL;
    }
    sfb_block_reset( SF_RESET_REASON_ADDR , 1 ); 
    return sfb_write_buf( SF_RESET_REASON_ADDR, (uint8_t *)data, dlen );
}

/** ****************************************************************************
* @remarks      uint32_t save_reset_reason_read( uint8_t *data, uint16_t dlen )
* @brief        读出设备的重启原因
* @param[in]     dlen 读取数据长度
* @param[out]    *data 数据目标地址地址
* @return        pdPASS 成功，pdFAIL 失败；
* @attention     无
*******************************************************************************/
uint32_t save_reset_reason_read( uint8_t *data, uint16_t dlen )
{
    return sfb_read_buf( SF_RESET_REASON_ADDR, (uint8_t *)data, dlen );
}


/** ****************************************************************************
* @remarks       uint32_t save_lbs_key_write_to_flash( uint8_t *data, uint16_t len )
* @brief         将LBS数据保存到FLASH中
* @param[in]     *data 数据源地址，len数据长度
* @param[out]    无
* @return        pdPASS 成功，pdFAIL 失败。
* @attention     数据长度不大于 4096 - 3 个字节；
*******************************************************************************/
uint32_t save_lbs_key_write_to_flash( uint8_t *data, uint16_t len )
{
    uint8_t *pmem =  NULL;

    if( ( data == NULL ) || ( len == 0 ) || ( len > ( SF_LBS_KEY_SIZE - 3 )) ) /*减去数据长度和校验值*/
    {
        return pdFAIL;
    }
    pmem = (uint8_t *)gaoz_malloc_mem( len + 8 );
    if( pmem != NULL )
    {
        memset( (uint8_t *)pmem, 0xFF, ( len + 8 ) );
        pmem[0] = ( uint8_t )( ( len & 0xFF00 ) >> 8 ); 
        pmem[1] = ( uint8_t )( len & 0x00FF );                                  /*数据长度*/
        pmem[2] = calculate_crc8( data , len );                                 /*CRC校验*/
        memcpy( (uint8_t *)&pmem[3], (uint8_t *)data, len );                    /*拷贝数据内容*/
        sfb_block_reset( SF_LBS_KEY_ADDR, SF_LBS_KEY_FLAG_SECTORS );            /*擦除FLASH*/
        if( sfb_write_buf( SF_LBS_KEY_ADDR, pmem, ( len + 3 ) ) == pdFAIL )     /*将数据写入到FLASH中*/
        {
            return pdFAIL;
        }
        gaoz_free_mem( (void * )pmem );
    }
    
    return pdPASS;
}

/** ****************************************************************************
* @remarks       uint32_t save_lbs_key_read_form_flash( uint8_t *data, uint16_t *len )
* @brief         读取LBD FLASH中数据
* @param[in]     *len 源地址数据长度
* @param[out]    *data 数据源地址，*len数据长度
* @return        pdPASS 成功，pdFAIL 失败。
* @attention     读取得数据长度小于 4096 -3 个字节。
*******************************************************************************/
uint32_t save_lbs_key_read_form_flash( uint8_t *data, uint16_t *len )
{
    uint8_t msg[3] = { 0 };
    uint16_t msg_len = 0;    

    if(( data == NULL ) || ( len == NULL ))
    {
        return pdFAIL;
    }
    if( sfb_read_buf( SF_LBS_KEY_ADDR, ( uint8_t* )msg, 3 ) == pdFAIL )
    {
        return pdFAIL;
    }
    msg_len = ( uint16_t )(( msg[0] << 8 ) | msg[1] );  /*数据长度*/
    if( msg_len > ( SF_LBS_KEY_SIZE - 3 ) )
    {
        return pdFAIL;
    }
    /*如果数据源长度小于目标数据时，返回错误状态*/
    if( msg_len > *len )
    {
        return pdFAIL;
    }
    if( sfb_read_buf( ( SF_LBS_KEY_ADDR + 3 ), ( uint8_t* )data, msg_len ) == pdFAIL )
    {
        return pdFAIL;
    }
    /*如果CRC校验错误时返回错误状态*/
    if( msg[2] != calculate_crc8( data , msg_len ) )
    {
        return pdFAIL;
    }
    *len = msg_len;
    
    return pdPASS;
}

/** ****************************************************************************
* @remarks       uint32_t save_lbs_key_flash_clear( void )
* @brief         清楚LBS存储的数据
* @param[in]     无
* @param[out]    无
* @return        无
* @attention     
*******************************************************************************/
void save_lbs_key_flash_clear( void )
{
    sfb_block_reset( SF_LBS_KEY_ADDR, SF_LBS_KEY_FLAG_SECTORS );            /*擦除FLASH*/
}

/** ****************************************************************************
* @remarks       static void save_data_printf_data_fun( save_data_mode_e mode , sfb_buf_rt_t *sfb_handle , uint8_t * p_data , uint16_t d_len )
* @brief         打印SAVE 数据
* @param[in]     mode 打印模式 SAVE_DATA_WRITE 写数据  SAVE_DATA_READ 读数据
* @param[in]     *sfb_handle 操作句柄
* @param[in]     *p_data 数据的目标地址
* @param[in]     d_len 网络节点
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
static void save_data_printf_data_fun( save_data_mode_e mode , uint32_t handle_id , uint8_t *p_data , uint16_t d_len )
{   
    uint8_t *pBuf = NULL , i = 0;
    uint16_t data_len = 0 ,print = 0;
    
    if( handle_id >= SAVE_RAM_OPEN_MAX_NUM )
    {
        return;
    }
    /*动态申请空间，由于接收的数据需要转变为STRING类型，数据量是原始数据的2倍*/
    pBuf = gaoz_malloc_mem( d_len * 2  + 50 );
    if( pBuf != NULL )
    {
        if( mode == SAVE_DATA_WRITE )
        {
            data_len = sprintf((char *)pBuf,"Save management writer data:%d,%d(handle,len)",(UINT32)handle_id ,d_len );
        }
        else// if( mode == SAVE_DATA_READ )
        {
            data_len = sprintf((char *)pBuf,"Save management read data:%d,%d(handle,len)",(UINT32)handle_id ,d_len );
        }
        data_len += HexToAsciiString((char *)&pBuf[data_len],( const char * )p_data, d_len);
        pBuf[ data_len ] = '\r';
        data_len++;
        pBuf[ data_len ] = '\n';
        data_len++;
        /*发送数据*/
        print = data_len / DEBUG_UART_TX_QUEUE_LEN;
        for( i = 0 ; i < print ; i ++ )
        {
            log_debug_send(DEBUG_MODE,SAVE_MAN_NAME ,&pBuf[i*DEBUG_UART_TX_QUEUE_LEN],DEBUG_UART_TX_QUEUE_LEN);
        }
        print = data_len % DEBUG_UART_TX_QUEUE_LEN;
        if( print != 0 )
        {
            log_debug_send(DEBUG_MODE,SAVE_MAN_NAME ,&pBuf[i*DEBUG_UART_TX_QUEUE_LEN],print);
        }
        gaoz_free_mem( (void *)pBuf );
    }
}

/** ****************************************************************************
* @remarks       static void save_data_handle_task( void * pvParameters )
* @brief         SAVE 数据处理任务
* @param[in]     * pvParameters 任务参数
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
static void save_data_handle_task( void * pvParameters )
{
    ( void ) pvParameters;
    sfb_index_t windex;
    save_data_infor_t save_msg;
    sfb_buf_rt_t *handle = NULL;
    uint8_t *write_p = NULL;
    uint16_t write_len = 0 ,ram_num = 0 ;
    uint32_t flash_num = 0;
    uint32_t *handle_num = NULL;
    mon_reg_task_dog( 60 * GAOZ_TICK_PERIOD_S ,(uint8_t *)SAVE_MAN_NAME , TASK_SEM_YES ); /*注册任务看门狗*/
    log_debug_send(DEBUG_MODE,SAVE_MAN_NAME ,"Save data management task started successfully\r\n",0);
    for( ;; )
    {   
        mon_reset_task_dog();
        if( save_data_queue_get( &save_msg ) == pdPASS )  /*获取消息邮箱中的数据*/
        {
            save_data_printf_data_fun( SAVE_DATA_WRITE , save_msg.handle_id , (uint8_t *)save_msg.data , save_msg.len );
            /*将数据写入到RAM数据空间中*/
            if( save_ram_unit_write( save_msg.handle_id ,(uint8_t *)save_msg.data, save_msg.len ) == pdFAIL )
            {
                log_debug_printf( ERROR_MODE,SAVE_MAN_NAME ,"[%s]Save data management writer ram error,handle is:%d\r\n",sys_err_infor_pointer_get( 8 ),save_msg.handle_id );
            }
            save_ram_data_len_get( save_msg.handle_id ,&ram_num );
            if( save_msg.data != NULL )
            {
                gaoz_free_mem( (void * )save_msg.data );
            }
            /*读取数据，TAIL空间中的数据保存到外部FLASH中*/
            handle = ram_buffer[save_msg.handle_id].sfb_handle;
            handle_num = &ram_buffer[save_msg.handle_id].handle_num;
            if( handle->sfb_st == SFB_SPACE_STATE_OK )
            {
                write_p = (uint8_t *)gaoz_malloc_mem( handle->sfb_set.unit_sz );
                memset((uint8_t *)write_p ,0x00 , handle->sfb_set.unit_sz );
                if( save_ram_tail_data_get( save_msg.handle_id ,write_p, &write_len ) == pdPASS )
                {
                    memset((uint8_t *)&windex , 0xFF , sizeof( sfb_index_t ));
                    windex.ucsfcrc = calculate_crc8( write_p , windex.usdatalen );
                    windex.usdatalen = save_msg.len;
                    if( sfb_unit_write( handle , write_p , &windex ) == pdFAIL )
                    {
                        handle->sfb_st = SFB_SPACE_STATE_ERR;
                        log_debug_printf( ERROR_MODE,SAVE_MAN_NAME ,"[%s]Save data management writer flash error,handle is:%d\r\n",sys_err_infor_pointer_get( 9 ),save_msg.handle_id );
                    }
                    else
                    {
                        sfb_write_handle_position( handle, handle_num );
                    }
                }
                gaoz_free_mem( (void * )write_p );
            }
            sfb_units_cn_get( handle, &flash_num );
            log_debug_printf( DEBUG_MODE,SAVE_MAN_NAME ,"Save data management writer num:%d,%d(RAM,FLASH)\r\n",ram_num , flash_num );
        }
    }
}
